package com.glp.work.flow.controller;

import com.github.pagehelper.PageInfo;
import com.glp.common.reponse.BaseResponse;
import com.glp.common.reponse.BaseResult;
import com.glp.work.flow.constant.APICode;
import com.glp.work.flow.constant.Constants;
import com.glp.work.flow.constant.ProcessStatusEnum;
import com.glp.work.flow.dto.*;
import com.glp.work.flow.dto.request.ModelDto;
import com.glp.work.flow.dto.request.ModelListRequestDto;
import com.glp.work.flow.dto.request.ProDefDTO;
import com.glp.work.flow.exception.APIException;
import com.glp.work.flow.pojo.FlowTaskDto;
import com.glp.work.flow.pojo.WfPlatformDefModle;
import com.glp.work.flow.service.UserService;
import com.glp.work.flow.service.UserTaskAssignService;
import com.glp.work.flow.service.WfPlatformDefService;
import com.glp.work.flow.workflow.plugin.flowable.dto.*;
import com.glp.work.flow.workflow.plugin.flowable.service.FlowProcessDefinitionService;
import com.glp.work.flow.workflow.plugin.flowable.service.FlowTaskService;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Model;
import org.flowable.validation.ValidationError;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 工作流POC程序-任务
 *
 * @author Pan Wang
 * @date 2019年03月13日 10:51:50
 */
@RestController
@RequestMapping("/pd")
@Api(tags = "工作流定义")
@Slf4j
public class WFDefinitionController {

    @Resource
    private FlowTaskService flowTaskService;

    @Resource
    private FlowProcessDefinitionService flowProcessDefinitionService;

    @Resource
    private UserService userService;

    @Resource
    private WfPlatformDefService wfPlatformDefService;

    @Resource
    private UserTaskAssignService userTaskAssignService;

    @Autowired
    RepositoryService repositoryService;



    @GetMapping("/queryProcessAndModel")
    @ApiOperation(value = "查询模板和流程定义列表信息2")
    public BaseResult<PageInfo<ProcessAndModelVo>> queryProcessAndModel2(ProcessAndModelDto processAndModelDto, Integer pageSize, Integer pageNum) {
        try {
            return BaseResponse.success(flowProcessDefinitionService.queryProcessAndModel2(processAndModelDto, pageSize, pageNum));
        } catch (APIException e) {
            log.error(e.toString(), e);
            return e.parse();
        }
    }





    @GetMapping("/queryProcessDefinitionList")
    @ApiOperation(value = "查询流程定义列表")
    public BaseResult<PageInfo<ProcessDefinitionEntitDTO>> queryProcessDefinitionList(ProcessDefQueryDto flowDataListDto) {
        try {
            return BaseResponse.success(flowProcessDefinitionService.queryProcessDefinitionList(flowDataListDto));
        } catch (APIException e) {
            log.error(e.toString(), e);
            return e.parse();
        }
    }

    @ApiOperation(value = "上传BPMN文件")
    @SuppressWarnings("unchecked")
    @PostMapping("/upload")
    @ResponseBody
    public BaseResult<String> upload(@RequestParam("file") MultipartFile file, @RequestHeader String userNo) {
        String modelId = null;
        if (file.isEmpty()) {
            return BaseResponse.error("上传失败，请选择文件");
        }

        try {
            modelId = flowProcessDefinitionService.uploadBPMN(file, userNo);

            log.info("上传成功:{}", file.getOriginalFilename());

            return BaseResponse.success(modelId);

        } catch (APIException e) {
            log.error(e.toString(), e);
            return e.parse();
        }
    }

    @ApiOperation(value = "导出BPMN文件")
    @GetMapping("/downLoad/{modeId}")
    public void downLoad(@PathVariable(value = "modeId") String modeId, HttpServletResponse response) {
        if (StringUtils.isBlank(modeId)) {
            throw new APIException(APICode.AUTH_MISS_APPID, "下载失败，modeId不能为null。");
        }
        try (ByteArrayOutputStream baos = flowProcessDefinitionService.downLoadBpmn(modeId)) {
            response.setCharacterEncoding("utf-8");
            response.setContentType("multipart/form-data");
            response.setHeader("Content-Disposition", "attachment;fileName=" + modeId + ".bpmn20.xml");
            response.getOutputStream().write(baos.toByteArray());
        } catch (Exception e) {
            log.error("下载失败。" + modeId, e);
            throw new APIException(APICode.AUTH_MISS_APPID, "下载失败。" + modeId);
        }
    }


    @ApiOperation(value = "获取流程图")
    @GetMapping(value = "/getFowImg", produces = "image/PNG")
    public void getFowImg(HttpServletResponse httpServletResponse, String processDefinitionId, String processInstanceId, String resourceType) {
        try {
            InputStream in = flowProcessDefinitionService.resourceRead(processDefinitionId, processInstanceId, resourceType);

            OutputStream out = null;
            byte[] buf = new byte[1024];
            int legth = 0;
            try {
                out = httpServletResponse.getOutputStream();
                while ((legth = in.read(buf)) != -1) {
                    out.write(buf, 0, legth);
                }
            } finally {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            }

        } catch (Exception ex) {
            log.error("getFowImg error", ex);
        }
    }

    @ApiOperation(value = "部署流程")
    @PostMapping("/deploy")
    @ResponseBody
    public BaseResult<String> deploy(@RequestParam("modelId") String modelId) {
        try {
            modelId = flowProcessDefinitionService.deploy(modelId);
            log.info("部署成功");
            return BaseResponse.success(modelId);
        } catch (Exception e) {
            log.error(e.toString(), e);
            return BaseResponse.error(e.getMessage());
        }
    }

    @ApiOperation(value = "删除流程")
    @PostMapping("/delete")
    @ResponseBody
    public BaseResult<String> delete(@RequestParam("modelId") String modelId) {
        try {
            flowProcessDefinitionService.delete(modelId);
            log.info("删除成功");
            return BaseResponse.success(modelId);
        } catch (Exception e) {
            log.error(e.toString(), e);
            return BaseResponse.error(e.getMessage());
        }
    }

    @ApiOperation(value = "启动流程")
    @PostMapping("/start")
    @ResponseBody
    public BaseResult<String> start(FlowStartDTO flowStartDto) {
        try {

            Map<String, Object> vars = Maps.newHashMap();

            Map formData = new Gson().fromJson(flowStartDto.getFormData(), HashMap.class);

            /**
             * 设置流程发起人-可以在后面流程中驳回重新办理
             */
            String instanceId = flowTaskService.startProcess(flowStartDto.getProcDefKey(), flowStartDto.getBusinessId(), formData, vars, flowStartDto.getUserNo(), null, null);
            log.info("上传成功");
            return BaseResponse.success(instanceId);
        } catch (Exception e) {
            log.error(e.toString(), e);
            return BaseResponse.error(e.getMessage());
        }
    }

//
//   @ApiOperation(value = "启动流程")
//   @PostMapping("/useAudit")
//   @ResponseBody
//    public BaseResult<String> userAudit(String procInsId,String assignee, Boolean isPass, String comment) {
//       try {
//           /**
//            * 设置流程发起人-可以在后面流程中驳回重新办理
//            */
//           FlowTaskDto flowTaskDto = new FlowTaskDto();
//           flowTaskDto.setProcInsId(procInsId);
//           flowTaskDto.setAssignee(assignee);
//           flowTaskDto.setPass(isPass);
//           flowTaskDto.setComment(comment);
//    	   flowTaskService.userAudit(flowTaskDto);;
//         log.info("上传成功");
//         return BaseResponse.success();
//       } catch (Exception e) {
//     	log.error(e.toString(), e);
//     	return BaseResponse.error(e.getMessage());
//       }
//   }

    @GetMapping("/queryTodoList")
    @ApiOperation(value = "查询待办任务列表")
    public BaseResult<FlowDataListDTO<ProcessDefinitionEntitDTO>> queryTodoList(QueryTodoListDTO queryTodoListDTO) {
        try {
            FlowDataListDTO<FlowTaskDto> flowDataListDto =
                    new FlowDataListDTO(queryTodoListDTO.getPageSize(), queryTodoListDTO.getPageNum());

            FlowTaskDto flowTaskDto = new FlowTaskDto();

            flowTaskDto.setAssignee(queryTodoListDTO.getUserNo());

            return BaseResponse.success(flowTaskService.queryTodoList(flowDataListDto, flowTaskDto, queryTodoListDTO.getUserNo()));
        } catch (APIException e) {
            log.error(e.toString(), e);
            return e.parse();
        }
    }

    @GetMapping("/queryTaskHistoriesByUserNo")
    public BaseResult queryHistories(@RequestParam("userNo") String userNo) {
        return BaseResponse.success(flowTaskService.queryTaskHistories(userNo));
    }


    @GetMapping("/queryTaskHistories")
    public BaseResult queryTaskHistories(@RequestParam("procInsId") String procInsId) {
        return BaseResponse.success(flowTaskService.queryTaskHistories(procInsId));
    }

    @ApiOperation(value = "查看流程定义")
    @RequestMapping(value = "/getPd/{key}", method = RequestMethod.GET)
    public Map<String, Object> getProcessDefinitionByKey(@PathVariable(value = "key") String key) {
        return flowProcessDefinitionService.getProcessDefinitionByKey(key);
    }

    @ApiOperation(value = "模板列表")
    @GetMapping("/models")
    public BaseResult getModels(ModelListRequestDto dto) {
        return flowProcessDefinitionService.getModels(dto);
    }

    /**
	 *第一版  添加模型
	 */
    @ApiOperation(value = "添加模型")
    @PostMapping("/add/model")
    public BaseResult addModel(@RequestBody ModelCreateDto dto) {
        return flowProcessDefinitionService.addModel(dto);
    }

    /**
     *第二版  添加模型
     */
    @ApiOperation(value = "添加模型(version--2.0)")
    @PostMapping("/add/modelnew")
    public BaseResult addModelNew(@RequestHeader("userNo") String userNo, @RequestBody ModelCreateDto dto) {
        return flowProcessDefinitionService.addModelNew(userNo, dto);
    }

    @ApiOperation(value = "模型详情,返回编辑器需要的json")
    @GetMapping("/models/info")
    public BaseResult modelInfo(@RequestParam("modelId") String modelId) {
        return flowProcessDefinitionService.modelInfo(modelId);
    }

    @ApiOperation(value = "模型编辑校验")
    @PostMapping("/models/validate")
    public List<ValidationError> validate(@RequestBody @ApiParam(value = "编辑器保存的模型json", required = true) String json) {
        return flowProcessDefinitionService.validate(json);
    }

    /**
     *第一版 模型保存
     */
    @ApiOperation(value = "模型保存")
    @PostMapping("/models/{id}/save")
    public BaseResult modelSave(@PathVariable("id") String modelId, @RequestBody ModelSaveDto dto) {
        return flowProcessDefinitionService.saveModel(modelId, dto);
    }

    /**
     *第二版  设计保存
     */
    @ApiOperation(value = "设计保存(version--2.0)")
    @PostMapping("/models/{id}/savetow")
    public BaseResult modelSave2(@PathVariable("id") String modelId, @RequestBody ModelSaveDto dto, @RequestHeader String userNo) {
        return flowProcessDefinitionService.saveModel2(modelId, dto, userNo);
    }

    /**
     *第二版  详情保存  包含权限设置  节点设置
     */
    @ApiOperation(value = "模型保存(全)")
    @PostMapping("/models/{id}/savenew")
    public BaseResult modelSaveNew(@RequestHeader String userNo, @RequestBody ModelDto dto) {

        return flowProcessDefinitionService.saveModelNew(dto, userNo);
    }

    @ApiOperation(value = "模糊查找用户")
    @PostMapping("/models/user/{name}")
    public BaseResult<List<UserEntity>> findUsers(@PathVariable("name") String name) {
        UserEntity user = new UserEntity();
        user.setUserName(name);
        return userService.getUserList(user);
    }

    @ApiOperation(value = "激活，挂起")
    @PostMapping("/process/{id}/{status}")
    public BaseResult modelStatus(@ApiParam(value = "procDefId", required = true) @PathVariable("id") String procDefId, @ApiParam(value = "激活状态传入active或者suspend", required = true) @PathVariable(value = "status") String status) {
        return flowProcessDefinitionService.modelStatusUpdate(procDefId, status);
    }

    @ApiOperation(value = "查询流程用户任务列表")
    @PostMapping("/models/details/{modelId}")
    public BaseResult<UserTaskVoDto> userTaskDetails(@PathVariable("modelId") String modelId) {
        return flowProcessDefinitionService.userTaskDetails(modelId);
    }

    @ApiOperation("超级流程发起工作流")
    @PostMapping("/superprocess")
    public BaseResult initiateOrder(@RequestHeader String userNo, @RequestBody Map<String, Object> preVariable) {
        log.info("超级流程发起工作流：{}",preVariable);
        Map process = (Map) preVariable.get("processVariable");
        String superProcess = (String) process.get("superProcess");
        superProcess = superProcess + "," + userNo;
        BaseResult<UserDTO> b = userService.getPersonInfo(userNo);
        UserDTO user = b.getData();
        if (user == null) {
            throw new APIException(APICode.DATA_ERROR, "超级流程异常！当前用户信息不存在！");
        }
        superProcess = superProcess + "," + user.getName();
        String[] split = superProcess.split(",");
        List<WfPlatformDefModle> wfPlatformDefModles = null;
        wfPlatformDefModles = wfPlatformDefService.wfPlantDefModelKey(preVariable.get("modelKey").toString());
        if (ProcessStatusEnum.ACTIVE.getCode().equals(split[1])) {
            Model model = repositoryService.getModel(split[2]);
            if (CollectionUtils.isEmpty(wfPlatformDefModles)) {
                throw new APIException(APICode.DATA_ERROR, "尚未授权应用！");
            }
            ProDefDTO req = new ProDefDTO();
            req.setProDefId(split[0]);
            List<ProcTaskInfoDTO> taskList = userTaskAssignService.queryProAllTaskDefInfoNew(req);
            for (ProcTaskInfoDTO proc : taskList) {
                if (StringUtils.isEmpty(proc.getType())) {
                    throw new APIException(APICode.DATA_ERROR, "节点【" + proc.getTaskDefKey() + "】未设置权限");
                }
                if (Constants.STATUS_1.equals(proc.getType())) {
                    if (CollectionUtils.isEmpty(proc.getTaskReceiveList())) {
                        throw new APIException(APICode.DATA_ERROR, "节点【" + proc.getTaskDefKey() + "】未设置权限");
                    }
                }
                if (Constants.STATUS_0.equals(proc.getType())) {
                    if (CollectionUtils.isEmpty(proc.getTaskRoleReceiveList())) {
                        throw new APIException(APICode.DATA_ERROR, "节点【" + proc.getTaskDefKey() + "】未设置权限");
                    }
                }
            }
        }
        if ("LC000656".equals(preVariable.get("modelKey"))) {
            /**
             * split[0]:流程id
             * split[1]:状态
             * split[2]:模板id
             */
            BaseResult baseResult = flowProcessDefinitionService.modelStatusUpdateNew(split[0], split[1], split[2], userNo, user.getName());
            return baseResult;
        }

        return flowProcessDefinitionService.processInitate(preVariable, user, superProcess, split, wfPlatformDefModles);

    }

}
